package cn.demoncat.util.exception;

import cn.demoncat.util.lang.StringUtil;
import cn.demoncat.util.lang.entity.MapSs;

/**
 * 请求远程服务异常
 * 
 * 场景：调用远程服务（内部，外部）时，发生请求延迟、网络中断、错误响应等情况 使用：程序中请求失败时直接抛出异常，由统一异常处理器拦截
 *
 * @author 延晓磊
 *
 * @since 2017年3月26日
 */
public class RestRuntimeException extends ErrorRuntimeException {

	/**
	 * 错误消息
	 *
	 */
	public interface ErrorMsg{

		String COMMON = "请求远程服务失败";

		String API = "请求第三方服务失败[API]";

		String REST = "请求远程服务失败[REST]";

		String RPC = "调用远程服务失败[RPC]";

		String HTTP = "请求远程服务失败[Http]";

		String SOCKET = "调用远程服务失败[Socket]";

		/**
		 * 消息分隔符
		 */
		String MSG_SEPARATOR = " -> ";
	}

	/**
	 * 错误类型
	 *
	 */
	public interface ErrorType{

		/**
		 * 第三方API
		 */
		String API = "0";
		/**
		 * Spring Cloud Feign
		 */
		String REST = "1";
		/**
		 * RPC
		 */
		String RPC = "2";
		/**
		 * Http Client
		 */
		String HTTP = "3";
		/**
		 * Socket
		 */
		String SOCKET = "4";

		/**
		 * 消息映射
		 */
		MapSs MAP = MapSs.getInstance(API, ErrorMsg.API, REST, ErrorMsg.REST, RPC, ErrorMsg.RPC, HTTP, ErrorMsg.HTTP, SOCKET, ErrorMsg.SOCKET);
	}
	
	/**
	 * 常用异常：请求远程服务失败
	 */
	public static final RestRuntimeException COMMON = new RestRuntimeException(ErrorMsg.COMMON);

	/**
	 * 常用异常：请求第三方服务失败，如支付渠道、短信渠道
	 */
	public static final RestRuntimeException API_ERROR = new RestRuntimeException(ErrorMsg.API);

	/**
	 * 常用异常：Spring Cloud 请求远程服务失败
	 */
	public static final RestRuntimeException REST_ERROR = new RestRuntimeException(ErrorMsg.REST);

	/**
	 * 常用异常：RPC 请求远程服务失败
	 */
	public static final RestRuntimeException RPC_ERROR = new RestRuntimeException(ErrorMsg.RPC);

	/**
	 * 常用异常：Http Client 请求远程服务失败
	 */
	public static final RestRuntimeException HTTP_ERROR = new RestRuntimeException(ErrorMsg.HTTP);

	/**
	 * 常用异常：Socket 请求远程服务失败
	 */
	public static final RestRuntimeException SOCKET_ERROR = new RestRuntimeException(ErrorMsg.SOCKET);

	public RestRuntimeException() {
		super();
	}

	public RestRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}

	public RestRuntimeException(String message, Throwable cause) {
		super(message, cause);
	}

	public RestRuntimeException(String message) {
		super(message);
	}

	public RestRuntimeException(Throwable cause) {
		super(cause);
	}

	/**
	 * 构造
	 *
	 * @param type
	 *            请求类型：0 API, 1 Spring Cloud,2 RPC，3 Http Client，4 Socket，其它 直接输出消息
	 * @param message
	 *            信息，null则只输出类型信息
	 */
	public RestRuntimeException(String type, String message) {
		this(getMsg(type, message));
	}

	/**
	 * 构造
	 *
	 * @param type
	 *            请求类型：0 API, 1 Spring Cloud,2 RPC，3 Http Client，4 Socket，其它 直接输出消息
	 * @param message
	 *            信息，null则只输出类型信息
	 */
	public RestRuntimeException(String type, String message, Throwable cause) {
		this(getMsg(type, message), cause);
	}

	/**
	 * 第三方服务API请求异常
	 *
	 * @param message
	 * @param cause
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException apiError(String message, Throwable cause) {
		return new RestRuntimeException(ErrorType.API, message, cause);
	}

	/**
	 * 第三方服务API请求异常
	 *
	 * @param message
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException apiError(String message) {
		return new RestRuntimeException(ErrorType.API, message);
	}

	/**
	 * 第三方服务API请求异常
	 *
	 * @param cause
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException apiError(Throwable cause) {
		return new RestRuntimeException(ErrorType.API, null, cause);
	}

	/**
	 * Spring Cloud Feign 调用异常
	 * 
	 * @param message
	 * @param cause
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException restError(String message, Throwable cause) {
		return new RestRuntimeException(ErrorType.REST, message, cause);
	}
	/**
	 * Spring Cloud Feign 调用异常
	 * 
	 * @param message
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException restError(String message) {
		return new RestRuntimeException(ErrorType.REST, message);
	}
	/**
	 * Spring Cloud Feign 调用异常
	 * 
	 * @param cause
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException restError(Throwable cause) {
		return new RestRuntimeException(ErrorType.REST, null, cause);
	}
	
	/**
	 * RPC 调用异常
	 * 
	 * @param message
	 * @param cause
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException rpcError(String message, Throwable cause) {
		return new RestRuntimeException(ErrorType.RPC, message, cause);
	}

	/**
	 * RPC 调用异常
	 * 
	 * @param message
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException rpcError(String message) {
		return new RestRuntimeException(ErrorType.RPC, message);
	}

	/**
	 * RPC 调用异常
	 * 
	 * @param cause
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException rpcError(Throwable cause) {
		return new RestRuntimeException(ErrorType.RPC, null, cause);
	}
	
	/**
	 * Http Client 调用异常：URL错误
	 * 
	 * @param url
	 * @param cause
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException httpUrlError(String url, Throwable cause) {
		return new RestRuntimeException(ErrorType.HTTP, "url = " + url, cause);
	}
	
	/**
	 * Http Client 调用异常：状态错误
	 * 
	 * @param url		URL
	 * @param status	响应码
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException httpStatusError(String url, Object status) {
		return new RestRuntimeException(ErrorType.HTTP, StringUtil.logFormat("url= {}, status = {}", url, status));
	}
	
	/**
	 * Http Client 调用异常
	 * 
	 * @param message
	 * @param cause
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException httpError(String message, Throwable cause) {
		return new RestRuntimeException(ErrorType.HTTP, message, cause);
	}
	
	/**
	 * Http Client 调用异常
	 * 
	 * @param message
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException httpError(String message) {
		return new RestRuntimeException(ErrorType.HTTP, message);
	}
	
	/**
	 * Http Client 调用异常
	 * 
	 * @param cause
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException httpError(Throwable cause) {
		return new RestRuntimeException(ErrorType.HTTP, null, cause);
	}
	
	/**
	 * Socket 调用异常
	 * 
	 * @param message
	 * @param cause
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException socketError(String message, Throwable cause) {
		return new RestRuntimeException(ErrorType.SOCKET, message, cause);
	}
	/**
	 * Socket 调用异常
	 * 
	 * @param message
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException socketError(String message) {
		return new RestRuntimeException(ErrorType.SOCKET, message);
	}
	/**
	 * Socket 调用异常
	 * 
	 * @param cause
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月28日
	 */
	public static RestRuntimeException socketError(Throwable cause) {
		return new RestRuntimeException(ErrorType.SOCKET, null, cause);
	}

	/**
	 * 整合异常消息
	 *
	 * @param type
	 *            请求类型：0 API, 1 Spring Cloud,2 RPC，3 Http Client，4 Socket，其它 直接输出消息
	 * @param msg
	 *            信息，null则只输出类型信息
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2017年12月21日
	 */
	public static String getMsg(String type, String msg) {
		//请求类型
		String typeMsg = ErrorType.MAP.get(type);
		//异常消息
		if (typeMsg == null) {
			return StringUtil.toDefault(msg, ErrorMsg.COMMON);
		}
		if (msg == null) {
			return typeMsg;
		}
		return typeMsg + ErrorMsg.MSG_SEPARATOR + msg;
	}
}
